Implements event batch id to events to display multiple events at the same time
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
0163c7a105
commit
bc9b3ed964
|
@ -9,7 +9,7 @@ use crate::static_data::Species;
|
||||||
use crate::static_data::{Form, Statistic};
|
use crate::static_data::{Form, Statistic};
|
||||||
|
|
||||||
/// A function that will be called when an event occured.
|
/// A function that will be called when an event occured.
|
||||||
type EvtHookFn = Box<dyn Fn(&Box<&Event>)>;
|
type EvtHookFn = Box<dyn Fn(Arc<EventData>, EventBatchId)>;
|
||||||
/// A collection of event hooks.
|
/// A collection of event hooks.
|
||||||
type EvtHookCollection = Vec<EvtHookFn>;
|
type EvtHookCollection = Vec<EvtHookFn>;
|
||||||
|
|
||||||
|
@ -35,12 +35,12 @@ impl EventHook {
|
||||||
|
|
||||||
/// Run a new event. This will send the event to all externally defined event listeners. It will
|
/// Run a new event. This will send the event to all externally defined event listeners. It will
|
||||||
/// dispose of the event afterwards.
|
/// dispose of the event afterwards.
|
||||||
pub fn trigger(&self, evt: Event) {
|
pub fn trigger(&self, evt: EventData, batch_id: EventBatchId) {
|
||||||
let b = Box::new(&evt);
|
let b = Arc::new(evt);
|
||||||
#[allow(clippy::unwrap_used)] // This should never fail.
|
#[allow(clippy::unwrap_used)] // This should never fail.
|
||||||
let read_lock = self.evt_hook_function.read().unwrap();
|
let read_lock = self.evt_hook_function.read().unwrap();
|
||||||
for f in read_lock.iter() {
|
for f in read_lock.iter() {
|
||||||
f(&b);
|
f(b.clone(), batch_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ impl Debug for EventHook {
|
||||||
|
|
||||||
/// The different events that can occur during the battle, for which a GUI should show something.
|
/// The different events that can occur during the battle, for which a GUI should show something.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Event<'own> {
|
pub enum EventData {
|
||||||
/// A switch event happens when a Pokemon gets switched out for something else.
|
/// A switch event happens when a Pokemon gets switched out for something else.
|
||||||
Switch {
|
Switch {
|
||||||
/// The side the Pokemon got switched from/on
|
/// The side the Pokemon got switched from/on
|
||||||
|
@ -77,7 +77,7 @@ pub enum Event<'own> {
|
||||||
/// enjoy.
|
/// enjoy.
|
||||||
SpeciesChange {
|
SpeciesChange {
|
||||||
/// The pokemon that changed species.
|
/// The pokemon that changed species.
|
||||||
pokemon: &'own Pokemon,
|
pokemon: Pokemon,
|
||||||
/// The new species of the Pokemon.
|
/// The new species of the Pokemon.
|
||||||
species: Arc<dyn Species>,
|
species: Arc<dyn Species>,
|
||||||
/// The form of the species the Pokemon will have.
|
/// The form of the species the Pokemon will have.
|
||||||
|
@ -86,14 +86,14 @@ pub enum Event<'own> {
|
||||||
/// This event happens when a Pokemon changes form during battle. This is rather common.
|
/// This event happens when a Pokemon changes form during battle. This is rather common.
|
||||||
FormChange {
|
FormChange {
|
||||||
/// The pokemon that changed forms.
|
/// The pokemon that changed forms.
|
||||||
pokemon: &'own Pokemon,
|
pokemon: Pokemon,
|
||||||
/// The new form of the Pokemon.
|
/// The new form of the Pokemon.
|
||||||
form: Arc<dyn Form>,
|
form: Arc<dyn Form>,
|
||||||
},
|
},
|
||||||
/// This event happens when a Pokemon takes damage.
|
/// This event happens when a Pokemon takes damage.
|
||||||
Damage {
|
Damage {
|
||||||
/// The Pokemon that takes damage.
|
/// The Pokemon that takes damage.
|
||||||
pokemon: &'own Pokemon,
|
pokemon: Pokemon,
|
||||||
/// The source of damage.
|
/// The source of damage.
|
||||||
source: DamageSource,
|
source: DamageSource,
|
||||||
/// The health of the Pokemon before the damage.
|
/// The health of the Pokemon before the damage.
|
||||||
|
@ -104,7 +104,7 @@ pub enum Event<'own> {
|
||||||
/// This event happens when a Pokemon gets healed
|
/// This event happens when a Pokemon gets healed
|
||||||
Heal {
|
Heal {
|
||||||
/// The Pokemon that gets healed.
|
/// The Pokemon that gets healed.
|
||||||
pokemon: &'own Pokemon,
|
pokemon: Pokemon,
|
||||||
/// The health of the Pokemon before the heal.
|
/// The health of the Pokemon before the heal.
|
||||||
original_health: u32,
|
original_health: u32,
|
||||||
/// The health of the Pokemon after the heal.
|
/// The health of the Pokemon after the heal.
|
||||||
|
@ -113,24 +113,24 @@ pub enum Event<'own> {
|
||||||
/// This event happens when a Pokemon faints.
|
/// This event happens when a Pokemon faints.
|
||||||
Faint {
|
Faint {
|
||||||
/// The pokemon that has fainted.
|
/// The pokemon that has fainted.
|
||||||
pokemon: &'own Pokemon,
|
pokemon: Pokemon,
|
||||||
},
|
},
|
||||||
/// This event happens when a Pokemon uses a move on a target, just before any hits.
|
/// This event happens when a Pokemon uses a move on a target, just before any hits.
|
||||||
MoveUse {
|
MoveUse {
|
||||||
/// The data of the move used.
|
/// The data of the move used.
|
||||||
executing_move: &'own ExecutingMove,
|
executing_move: Arc<ExecutingMove>,
|
||||||
},
|
},
|
||||||
/// This event happens when a Pokemon missed.
|
/// This event happens when a Pokemon missed.
|
||||||
Miss {
|
Miss {
|
||||||
/// The pokemon that missed.
|
/// The pokemon that missed.
|
||||||
user: &'own Pokemon,
|
user: Pokemon,
|
||||||
},
|
},
|
||||||
/// The turn is finished running, waiting for new input.
|
/// The turn is finished running, waiting for new input.
|
||||||
EndTurn,
|
EndTurn,
|
||||||
/// A pokemon had its stat boost changed
|
/// A pokemon had its stat boost changed
|
||||||
StatBoostChange {
|
StatBoostChange {
|
||||||
/// The pokemon that had its stat boosts changed.
|
/// The pokemon that had its stat boosts changed.
|
||||||
user: &'own Pokemon,
|
user: Pokemon,
|
||||||
/// The statistic that changed.
|
/// The statistic that changed.
|
||||||
stat: Statistic,
|
stat: Statistic,
|
||||||
/// The value of the stat before the change.
|
/// The value of the stat before the change.
|
||||||
|
@ -138,4 +138,42 @@ pub enum Event<'own> {
|
||||||
/// The value of the stat after the change.
|
/// The value of the stat after the change.
|
||||||
new_value: i8,
|
new_value: i8,
|
||||||
},
|
},
|
||||||
|
/// Triggered when a move hits.
|
||||||
|
MoveHit {
|
||||||
|
/// The pokemon that used the move.
|
||||||
|
user: Pokemon,
|
||||||
|
/// The pokemon that was hit.
|
||||||
|
target: Pokemon,
|
||||||
|
/// The effectiveness of the move.
|
||||||
|
effectiveness: f32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allows for the batching of multiple events that should be shown at the same time.
|
||||||
|
#[derive(Default, Copy, Clone)]
|
||||||
|
pub struct EventBatchId {
|
||||||
|
/// The id of the batch.
|
||||||
|
batch_id: uuid::Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventBatchId {
|
||||||
|
/// Gets the batch id as two u64s.
|
||||||
|
pub fn as_u64_pair(&self) -> (u64, u64) {
|
||||||
|
self.batch_id.as_u64_pair()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new batch id from two u64s.
|
||||||
|
pub fn from_u64_pair(a: u64, b: u64) -> Self {
|
||||||
|
Self {
|
||||||
|
batch_id: uuid::Uuid::from_u64_pair(a, b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u128> for EventBatchId {
|
||||||
|
fn from(value: u128) -> Self {
|
||||||
|
Self {
|
||||||
|
batch_id: uuid::Uuid::from_u128(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@ use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::dynamic_data::choices::TurnChoice;
|
use crate::dynamic_data::choices::TurnChoice;
|
||||||
use crate::dynamic_data::event_hooks::Event;
|
use crate::dynamic_data::event_hooks::EventData;
|
||||||
use crate::dynamic_data::flow::target_resolver::resolve_targets;
|
use crate::dynamic_data::flow::target_resolver::resolve_targets;
|
||||||
use crate::dynamic_data::script_handling::{ScriptSource, ScriptWrapper};
|
use crate::dynamic_data::script_handling::{ScriptSource, ScriptWrapper};
|
||||||
use crate::dynamic_data::Battle;
|
|
||||||
use crate::dynamic_data::DamageSource;
|
use crate::dynamic_data::DamageSource;
|
||||||
use crate::dynamic_data::ExecutingMove;
|
use crate::dynamic_data::ExecutingMove;
|
||||||
use crate::dynamic_data::Pokemon;
|
use crate::dynamic_data::Pokemon;
|
||||||
|
use crate::dynamic_data::{Battle, EventBatchId};
|
||||||
use crate::static_data::MoveCategory;
|
use crate::static_data::MoveCategory;
|
||||||
use crate::{run_scripts, script_hook, PkmnError};
|
use crate::{run_scripts, script_hook, PkmnError};
|
||||||
|
|
||||||
|
@ -145,9 +145,12 @@ impl Battle {
|
||||||
if !executing_move.chosen_move().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(
|
||||||
executing_move: &executing_move,
|
EventData::MoveUse {
|
||||||
});
|
executing_move: executing_move.clone(),
|
||||||
|
},
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
let mut fail = false;
|
let mut fail = false;
|
||||||
script_hook!(fail_move, executing_move, &executing_move, &mut fail);
|
script_hook!(fail_move, executing_move, &executing_move, &mut fail);
|
||||||
if fail {
|
if fail {
|
||||||
|
@ -280,9 +283,12 @@ impl Battle {
|
||||||
// TODO: Deal with accuracy/evasion stats.
|
// TODO: Deal with accuracy/evasion stats.
|
||||||
if accuracy < 100 && self.random().get_max(100)? as u8 >= accuracy {
|
if accuracy < 100 && self.random().get_max(100)? as u8 >= accuracy {
|
||||||
script_hook!(on_move_miss, target, executing_move, target);
|
script_hook!(on_move_miss, target, executing_move, target);
|
||||||
self.event_hook().trigger(Event::Miss {
|
self.event_hook().trigger(
|
||||||
user: executing_move.user().deref(),
|
EventData::Miss {
|
||||||
});
|
user: executing_move.user().clone(),
|
||||||
|
},
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +312,16 @@ impl Battle {
|
||||||
hit_data.set_damage(damage);
|
hit_data.set_damage(damage);
|
||||||
}
|
}
|
||||||
if damage > 0 {
|
if damage > 0 {
|
||||||
target.damage(damage, DamageSource::MoveDamage)?;
|
let move_hit_event_batch = EventBatchId::default();
|
||||||
|
self.event_hook().trigger(
|
||||||
|
EventData::MoveHit {
|
||||||
|
user: executing_move.user().clone(),
|
||||||
|
target: target.clone(),
|
||||||
|
effectiveness,
|
||||||
|
},
|
||||||
|
move_hit_event_batch,
|
||||||
|
);
|
||||||
|
target.damage(damage, DamageSource::MoveDamage, move_hit_event_batch)?;
|
||||||
if !target.is_fainted() {
|
if !target.is_fainted() {
|
||||||
script_hook!(on_incoming_hit, target, executing_move, target, hit_index);
|
script_hook!(on_incoming_hit, target, executing_move, target, hit_index);
|
||||||
} else {
|
} else {
|
||||||
|
@ -352,9 +367,12 @@ impl Battle {
|
||||||
|
|
||||||
if number_of_hits == 0 {
|
if number_of_hits == 0 {
|
||||||
script_hook!(on_move_miss, target, executing_move, target);
|
script_hook!(on_move_miss, target, executing_move, target);
|
||||||
self.event_hook().trigger(Event::Miss {
|
self.event_hook().trigger(
|
||||||
user: executing_move.user().deref(),
|
EventData::Miss {
|
||||||
});
|
user: executing_move.user().clone(),
|
||||||
|
},
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !executing_move.user().is_fainted() {
|
if !executing_move.user().is_fainted() {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use atomig::Atomic;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use crate::dynamic_data::choices::TurnChoice;
|
use crate::dynamic_data::choices::TurnChoice;
|
||||||
use crate::dynamic_data::event_hooks::{Event, EventHook};
|
use crate::dynamic_data::event_hooks::{EventData, EventHook};
|
||||||
use crate::dynamic_data::models::battle_party::BattleParty;
|
use crate::dynamic_data::models::battle_party::BattleParty;
|
||||||
use crate::dynamic_data::models::battle_random::BattleRandom;
|
use crate::dynamic_data::models::battle_random::BattleRandom;
|
||||||
use crate::dynamic_data::models::battle_side::BattleSide;
|
use crate::dynamic_data::models::battle_side::BattleSide;
|
||||||
|
@ -333,7 +333,7 @@ impl Battle {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.data.current_turn_queue.write().take();
|
self.data.current_turn_queue.write().take();
|
||||||
self.data.event_hook.trigger(Event::EndTurn);
|
self.data.event_hook.trigger(EventData::EndTurn, Default::default());
|
||||||
let end_time = chrono::Utc::now();
|
let end_time = chrono::Utc::now();
|
||||||
let time = end_time - start_time;
|
let time = end_time - start_time;
|
||||||
match time.num_nanoseconds() {
|
match time.num_nanoseconds() {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use parking_lot::lock_api::RwLockReadGuard;
|
||||||
use parking_lot::{RawRwLock, RwLock};
|
use parking_lot::{RawRwLock, RwLock};
|
||||||
|
|
||||||
use crate::dynamic_data::choices::TurnChoice;
|
use crate::dynamic_data::choices::TurnChoice;
|
||||||
use crate::dynamic_data::event_hooks::Event;
|
use crate::dynamic_data::event_hooks::EventData;
|
||||||
use crate::dynamic_data::models::battle::Battle;
|
use crate::dynamic_data::models::battle::Battle;
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||||
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
||||||
|
@ -231,18 +231,24 @@ impl BattleSide {
|
||||||
pokemon.mark_opponent_as_seen(opponent.weak());
|
pokemon.mark_opponent_as_seen(opponent.weak());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
battle.event_hook().trigger(Event::Switch {
|
battle.event_hook().trigger(
|
||||||
|
EventData::Switch {
|
||||||
side_index: self.data.index,
|
side_index: self.data.index,
|
||||||
index,
|
index,
|
||||||
pokemon: Some(pokemon.clone()),
|
pokemon: Some(pokemon.clone()),
|
||||||
});
|
},
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
script_hook!(on_switch_in, pokemon, pokemon);
|
script_hook!(on_switch_in, pokemon, pokemon);
|
||||||
} else {
|
} else {
|
||||||
self.battle()?.event_hook().trigger(Event::Switch {
|
self.battle()?.event_hook().trigger(
|
||||||
|
EventData::Switch {
|
||||||
side_index: self.data.index,
|
side_index: self.data.index,
|
||||||
index,
|
index,
|
||||||
pokemon: None,
|
pokemon: None,
|
||||||
});
|
},
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -339,11 +345,14 @@ impl BattleSide {
|
||||||
}
|
}
|
||||||
|
|
||||||
data.pokemon.write().swap(a as usize, b as usize);
|
data.pokemon.write().swap(a as usize, b as usize);
|
||||||
self.battle()?.event_hook().trigger(Event::Swap {
|
self.battle()?.event_hook().trigger(
|
||||||
|
EventData::Swap {
|
||||||
side_index: data.index,
|
side_index: data.index,
|
||||||
index_a: a,
|
index_a: a,
|
||||||
index_b: b,
|
index_b: b,
|
||||||
});
|
},
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,13 @@ use parking_lot::lock_api::RwLockReadGuard;
|
||||||
use parking_lot::{RawRwLock, RwLock};
|
use parking_lot::{RawRwLock, RwLock};
|
||||||
|
|
||||||
use crate::defines::{LevelInt, MAX_MOVES};
|
use crate::defines::{LevelInt, MAX_MOVES};
|
||||||
use crate::dynamic_data::event_hooks::Event;
|
use crate::dynamic_data::event_hooks::EventData;
|
||||||
use crate::dynamic_data::models::battle::Battle;
|
use crate::dynamic_data::models::battle::Battle;
|
||||||
use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod};
|
use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod};
|
||||||
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
||||||
use crate::dynamic_data::{
|
use crate::dynamic_data::{
|
||||||
DynamicLibrary, Script, ScriptCategory, ScriptContainer, ScriptSet, VolatileScriptsOwner, WeakBattleReference,
|
DynamicLibrary, EventBatchId, Script, ScriptCategory, ScriptContainer, ScriptSet, VolatileScriptsOwner,
|
||||||
|
WeakBattleReference,
|
||||||
};
|
};
|
||||||
use crate::static_data::AbilityIndex;
|
use crate::static_data::AbilityIndex;
|
||||||
use crate::static_data::Form;
|
use crate::static_data::Form;
|
||||||
|
@ -396,12 +397,15 @@ impl Pokemon {
|
||||||
if changed {
|
if changed {
|
||||||
if let Some(battle) = self.get_battle() {
|
if let Some(battle) = self.get_battle() {
|
||||||
let new_value = self.stat_boost(stat);
|
let new_value = self.stat_boost(stat);
|
||||||
battle.event_hook().trigger(Event::StatBoostChange {
|
battle.event_hook().trigger(
|
||||||
user: self,
|
EventData::StatBoostChange {
|
||||||
|
user: self.clone(),
|
||||||
stat,
|
stat,
|
||||||
old_value,
|
old_value,
|
||||||
new_value,
|
new_value,
|
||||||
})
|
},
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
self.recalculate_boosted_stats()?;
|
self.recalculate_boosted_stats()?;
|
||||||
}
|
}
|
||||||
|
@ -531,11 +535,14 @@ impl Pokemon {
|
||||||
let r = self.data.battle_data.read();
|
let r = self.data.battle_data.read();
|
||||||
if let Some(battle_data) = &r.deref() {
|
if let Some(battle_data) = &r.deref() {
|
||||||
if let Some(battle) = battle_data.battle() {
|
if let Some(battle) = battle_data.battle() {
|
||||||
battle.event_hook().trigger(Event::SpeciesChange {
|
battle.event_hook().trigger(
|
||||||
pokemon: self,
|
EventData::SpeciesChange {
|
||||||
|
pokemon: self.clone(),
|
||||||
species,
|
species,
|
||||||
form,
|
form,
|
||||||
})
|
},
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -597,10 +604,13 @@ impl Pokemon {
|
||||||
let r = self.data.battle_data.read();
|
let r = self.data.battle_data.read();
|
||||||
if let Some(battle_data) = r.deref() {
|
if let Some(battle_data) = r.deref() {
|
||||||
if let Some(battle) = battle_data.battle() {
|
if let Some(battle) = battle_data.battle() {
|
||||||
battle.event_hook().trigger(Event::FormChange {
|
battle.event_hook().trigger(
|
||||||
pokemon: self,
|
EventData::FormChange {
|
||||||
|
pokemon: self.clone(),
|
||||||
form: form.clone(),
|
form: form.clone(),
|
||||||
})
|
},
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -679,7 +689,7 @@ impl Pokemon {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Damages the Pokemon by a certain amount of damage, from a damage source.
|
/// Damages the Pokemon by a certain amount of damage, from a damage source.
|
||||||
pub fn damage(&self, mut damage: u32, source: DamageSource) -> Result<()> {
|
pub fn damage(&self, mut damage: u32, source: DamageSource, evt_batch_id: EventBatchId) -> Result<()> {
|
||||||
if damage > self.current_health() {
|
if damage > self.current_health() {
|
||||||
damage = self.current_health();
|
damage = self.current_health();
|
||||||
}
|
}
|
||||||
|
@ -689,12 +699,15 @@ impl Pokemon {
|
||||||
let new_health = self.current_health() - damage;
|
let new_health = self.current_health() - damage;
|
||||||
if let Some(battle_data) = &self.data.battle_data.read().deref() {
|
if let Some(battle_data) = &self.data.battle_data.read().deref() {
|
||||||
if let Some(battle) = battle_data.battle() {
|
if let Some(battle) = battle_data.battle() {
|
||||||
battle.event_hook().trigger(Event::Damage {
|
battle.event_hook().trigger(
|
||||||
pokemon: self,
|
EventData::Damage {
|
||||||
|
pokemon: self.clone(),
|
||||||
source,
|
source,
|
||||||
original_health: self.current_health(),
|
original_health: self.current_health(),
|
||||||
new_health,
|
new_health,
|
||||||
});
|
},
|
||||||
|
evt_batch_id,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self
|
if self
|
||||||
|
@ -719,7 +732,9 @@ impl Pokemon {
|
||||||
let r = self.data.battle_data.read();
|
let r = self.data.battle_data.read();
|
||||||
if let Some(battle_data) = r.deref() {
|
if let Some(battle_data) = r.deref() {
|
||||||
if let Some(battle) = battle_data.battle() {
|
if let Some(battle) = battle_data.battle() {
|
||||||
battle.event_hook().trigger(Event::Faint { pokemon: self });
|
battle
|
||||||
|
.event_hook()
|
||||||
|
.trigger(EventData::Faint { pokemon: self.clone() }, Default::default());
|
||||||
script_hook!(on_faint, self, self, source);
|
script_hook!(on_faint, self, self, source);
|
||||||
script_hook!(on_remove, self,);
|
script_hook!(on_remove, self,);
|
||||||
|
|
||||||
|
@ -752,11 +767,14 @@ impl Pokemon {
|
||||||
let new_health = self.current_health() + max_amount;
|
let new_health = self.current_health() + max_amount;
|
||||||
if let Some(battle_data) = &self.data.battle_data.read().deref() {
|
if let Some(battle_data) = &self.data.battle_data.read().deref() {
|
||||||
if let Some(battle) = battle_data.battle() {
|
if let Some(battle) = battle_data.battle() {
|
||||||
battle.event_hook().trigger(Event::Heal {
|
battle.event_hook().trigger(
|
||||||
pokemon: self,
|
EventData::Heal {
|
||||||
|
pokemon: self.clone(),
|
||||||
original_health: self.current_health(),
|
original_health: self.current_health(),
|
||||||
new_health,
|
new_health,
|
||||||
});
|
},
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.data.current_health.store(new_health, Ordering::SeqCst);
|
self.data.current_health.store(new_health, Ordering::SeqCst);
|
||||||
|
|
|
@ -1,22 +1,25 @@
|
||||||
use crate::dynamic_data::{Event, Pokemon};
|
use crate::dynamic_data::{EventData, Pokemon};
|
||||||
use crate::ffi::ExternPointer;
|
use crate::ffi::ffi_handle::FromFFIHandle;
|
||||||
use crate::ffi::FFIHandle;
|
use crate::ffi::FFIHandle;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// The kind of the event.
|
/// The kind of the event.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn event_kind(ptr: ExternPointer<Event>) -> u8 {
|
extern "C" fn event_kind(ptr: FFIHandle<Arc<EventData>>) -> u8 {
|
||||||
match ptr.as_ref() {
|
match ptr.from_ffi_handle().deref() {
|
||||||
Event::Switch { .. } => 1,
|
EventData::Switch { .. } => 1,
|
||||||
Event::Swap { .. } => 2,
|
EventData::Swap { .. } => 2,
|
||||||
Event::SpeciesChange { .. } => 3,
|
EventData::SpeciesChange { .. } => 3,
|
||||||
Event::FormChange { .. } => 4,
|
EventData::FormChange { .. } => 4,
|
||||||
Event::Damage { .. } => 5,
|
EventData::Damage { .. } => 5,
|
||||||
Event::Heal { .. } => 6,
|
EventData::Heal { .. } => 6,
|
||||||
Event::Faint { .. } => 7,
|
EventData::Faint { .. } => 7,
|
||||||
Event::MoveUse { .. } => 8,
|
EventData::MoveUse { .. } => 8,
|
||||||
Event::Miss { .. } => 9,
|
EventData::Miss { .. } => 9,
|
||||||
Event::EndTurn => 10,
|
EventData::EndTurn => 10,
|
||||||
Event::StatBoostChange { .. } => 11,
|
EventData::StatBoostChange { .. } => 11,
|
||||||
|
EventData::MoveHit { .. } => 12,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,12 +46,12 @@ macro_rules! event_ffi {
|
||||||
}
|
}
|
||||||
/// The getter for the data for the relevant event.
|
/// The getter for the data for the relevant event.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn [<event_ $event_name:snake _data>](ptr: ExternPointer<Event>) -> [<$event_name Data>] {
|
extern "C" fn [<event_ $event_name:snake _data>](ptr: FFIHandle<Arc<EventData>>) -> [<$event_name Data>] {
|
||||||
if let Event::$event_name {
|
if let EventData::$event_name {
|
||||||
$(
|
$(
|
||||||
$par_name,
|
$par_name,
|
||||||
)+
|
)+
|
||||||
} = ptr.as_ref()
|
} = ptr.from_ffi_handle().deref()
|
||||||
{
|
{
|
||||||
$ctor
|
$ctor
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,29 @@
|
||||||
use crate::dynamic_data::Event;
|
use crate::dynamic_data::{EventBatchId, EventData};
|
||||||
|
use crate::ffi::ffi_handle::FFIHandle;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Wrapper class for easier use of an external function pointer.
|
/// Wrapper class for easier use of an external function pointer.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub(super) struct NativeEventHook {
|
pub(super) struct NativeEventHook {
|
||||||
/// The actual C function to be called.
|
/// The actual C function to be called. Note that we pass the batch id as a pair of u64s. This
|
||||||
f: extern "C" fn(*const Event<'_>),
|
/// is because u128 does not have a stable ABI yet.
|
||||||
|
f: extern "C" fn(FFIHandle<Arc<EventData>>, u64, u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NativeEventHook {
|
impl NativeEventHook {
|
||||||
/// Calls the actual wrapped function in the correct format.
|
/// Calls the actual wrapped function in the correct format.
|
||||||
fn call_self(&self, b: &&Event<'_>) {
|
fn call_self(&self, b: Arc<EventData>, batch_id: EventBatchId) {
|
||||||
(self.f)(*b as *const Event)
|
let batch_id = batch_id.as_u64_pair();
|
||||||
|
(self.f)(FFIHandle::get_handle(b.into()), batch_id.0, batch_id.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A tuple with the arguments of the event hook function
|
/// A tuple with the arguments of the event hook function
|
||||||
type EventHookArgs<'a, 'b, 'c> = (&'a Box<&'b Event<'c>>,);
|
type EventHookArgs<'a, 'b, 'c> = (Arc<EventData>, EventBatchId);
|
||||||
|
|
||||||
impl FnMut<EventHookArgs<'_, '_, '_>> for NativeEventHook {
|
impl FnMut<EventHookArgs<'_, '_, '_>> for NativeEventHook {
|
||||||
extern "rust-call" fn call_mut(&mut self, args: EventHookArgs<'_, '_, '_>) -> Self::Output {
|
extern "rust-call" fn call_mut(&mut self, args: EventHookArgs<'_, '_, '_>) -> Self::Output {
|
||||||
self.call_self(args.0)
|
self.call_self(args.0, args.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,12 +31,12 @@ impl FnOnce<EventHookArgs<'_, '_, '_>> for NativeEventHook {
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
|
||||||
extern "rust-call" fn call_once(self, args: EventHookArgs<'_, '_, '_>) -> Self::Output {
|
extern "rust-call" fn call_once(self, args: EventHookArgs<'_, '_, '_>) -> Self::Output {
|
||||||
self.call_self(args.0)
|
self.call_self(args.0, args.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fn<EventHookArgs<'_, '_, '_>> for NativeEventHook {
|
impl Fn<EventHookArgs<'_, '_, '_>> for NativeEventHook {
|
||||||
extern "rust-call" fn call(&self, args: EventHookArgs<'_, '_, '_>) -> Self::Output {
|
extern "rust-call" fn call(&self, args: EventHookArgs<'_, '_, '_>) -> Self::Output {
|
||||||
self.call_self(args.0)
|
self.call_self(args.0, args.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::defines::LevelInt;
|
use crate::defines::LevelInt;
|
||||||
use crate::dynamic_data::{Battle, DamageSource, DynamicLibrary, LearnedMove, MoveLearnMethod, Pokemon};
|
use crate::dynamic_data::{Battle, DamageSource, DynamicLibrary, EventBatchId, LearnedMove, MoveLearnMethod, Pokemon};
|
||||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||||
use crate::ffi::{FFIResult, OwnedPtrString};
|
use crate::ffi::{FFIResult, OwnedPtrString};
|
||||||
use crate::static_data::{
|
use crate::static_data::{
|
||||||
|
@ -397,8 +397,21 @@ extern "C" fn pokemon_is_on_battlefield(handle: FFIHandle<Pokemon>) -> u8 {
|
||||||
|
|
||||||
/// Damages the Pokemon by a certain amount of damage, from a damage source.
|
/// Damages the Pokemon by a certain amount of damage, from a damage source.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn pokemon_damage(handle: FFIHandle<Pokemon>, damage: u32, source: DamageSource) -> FFIResult<()> {
|
extern "C" fn pokemon_damage(
|
||||||
handle.from_ffi_handle().damage(damage, source).into()
|
handle: FFIHandle<Pokemon>,
|
||||||
|
damage: u32,
|
||||||
|
source: DamageSource,
|
||||||
|
evt_batch_id_1: u64,
|
||||||
|
evt_batch_id_2: u64,
|
||||||
|
) -> FFIResult<()> {
|
||||||
|
handle
|
||||||
|
.from_ffi_handle()
|
||||||
|
.damage(
|
||||||
|
damage,
|
||||||
|
source,
|
||||||
|
EventBatchId::from_u64_pair(evt_batch_id_1, evt_batch_id_2),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Heals the Pokemon by a specific amount. Unless allow_revive is set to true, this will not
|
/// Heals the Pokemon by a specific amount. Unless allow_revive is set to true, this will not
|
||||||
|
|
|
@ -100,6 +100,9 @@ pub(super) enum FFIObject {
|
||||||
MiscLibrary(Arc<dyn crate::dynamic_data::MiscLibrary>),
|
MiscLibrary(Arc<dyn crate::dynamic_data::MiscLibrary>),
|
||||||
ScriptResolver(Arc<dyn crate::dynamic_data::ScriptResolver>),
|
ScriptResolver(Arc<dyn crate::dynamic_data::ScriptResolver>),
|
||||||
DynamicLibrary(Arc<dyn crate::dynamic_data::DynamicLibrary>),
|
DynamicLibrary(Arc<dyn crate::dynamic_data::DynamicLibrary>),
|
||||||
|
|
||||||
|
// Events
|
||||||
|
Event(Arc<crate::dynamic_data::EventData>),
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for FFIObject {}
|
unsafe impl Send for FFIObject {}
|
||||||
|
@ -218,6 +221,7 @@ impl Hash for FFIObject {
|
||||||
Self::MiscLibrary(a) => Arc::as_ptr(a).hash(state),
|
Self::MiscLibrary(a) => Arc::as_ptr(a).hash(state),
|
||||||
Self::ScriptResolver(a) => Arc::as_ptr(a).hash(state),
|
Self::ScriptResolver(a) => Arc::as_ptr(a).hash(state),
|
||||||
Self::DynamicLibrary(a) => Arc::as_ptr(a).hash(state),
|
Self::DynamicLibrary(a) => Arc::as_ptr(a).hash(state),
|
||||||
|
FFIObject::Event(a) => Arc::as_ptr(a).hash(state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,6 +269,7 @@ impl PartialEq for FFIObject {
|
||||||
(Self::MiscLibrary(a), Self::MiscLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
(Self::MiscLibrary(a), Self::MiscLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
||||||
(Self::ScriptResolver(a), Self::ScriptResolver(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
(Self::ScriptResolver(a), Self::ScriptResolver(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
||||||
(Self::DynamicLibrary(a), Self::DynamicLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
(Self::DynamicLibrary(a), Self::DynamicLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
||||||
|
(Self::Event(a), Self::Event(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,3 +342,4 @@ ffi_obj_conversions!(Arc<dyn crate::dynamic_data::DamageLibrary>, DamageLibrary)
|
||||||
ffi_obj_conversions!(Arc<dyn crate::dynamic_data::MiscLibrary>, MiscLibrary);
|
ffi_obj_conversions!(Arc<dyn crate::dynamic_data::MiscLibrary>, MiscLibrary);
|
||||||
ffi_obj_conversions!(Arc<dyn crate::dynamic_data::ScriptResolver>, ScriptResolver);
|
ffi_obj_conversions!(Arc<dyn crate::dynamic_data::ScriptResolver>, ScriptResolver);
|
||||||
ffi_obj_conversions!(Arc<dyn crate::dynamic_data::DynamicLibrary>, DynamicLibrary);
|
ffi_obj_conversions!(Arc<dyn crate::dynamic_data::DynamicLibrary>, DynamicLibrary);
|
||||||
|
ffi_obj_conversions!(Arc<crate::dynamic_data::EventData>, Event);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
|
|
||||||
use crate::defines::LevelInt;
|
use crate::defines::LevelInt;
|
||||||
use crate::dynamic_data::{Battle, DynamicLibrary, LearnedMove, Pokemon, VolatileScriptsOwner};
|
use crate::dynamic_data::{Battle, DynamicLibrary, EventBatchId, LearnedMove, Pokemon, VolatileScriptsOwner};
|
||||||
use crate::script_implementations::wasm::export_registry::{
|
use crate::script_implementations::wasm::export_registry::{
|
||||||
get_value, get_value_arc, get_value_arc_void, get_value_call_getter, get_value_void, register, try_wasm, wasm_err,
|
get_value, get_value_arc, get_value_arc_void, get_value_call_getter, get_value_void, register, try_wasm, wasm_err,
|
||||||
wasm_ok, WasmResult, WasmVoidResult, WasmVoidResultExtension,
|
wasm_ok, WasmResult, WasmVoidResult, WasmVoidResultExtension,
|
||||||
|
@ -120,14 +120,16 @@ register! {
|
||||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||||
pokemon: ExternRef<Pokemon>,
|
pokemon: ExternRef<Pokemon>,
|
||||||
damage: u32,
|
damage: u32,
|
||||||
source: u8
|
source: u8,
|
||||||
|
event_batch_id_1: u64,
|
||||||
|
event_batch_id_2: u64,
|
||||||
) -> WasmVoidResult {
|
) -> WasmVoidResult {
|
||||||
unsafe {
|
unsafe {
|
||||||
let pokemon = match pokemon.value_func(&env) {
|
let pokemon = match pokemon.value_func(&env) {
|
||||||
Ok(pokemon) => pokemon,
|
Ok(pokemon) => pokemon,
|
||||||
Err(e) => return WasmVoidResult::err(e, &env),
|
Err(e) => return WasmVoidResult::err(e, &env),
|
||||||
};
|
};
|
||||||
match pokemon.damage(damage, transmute(source)) {
|
match pokemon.damage(damage, transmute(source), EventBatchId::from_u64_pair(event_batch_id_1, event_batch_id_2)) {
|
||||||
Ok(()) => WasmVoidResult::ok(),
|
Ok(()) => WasmVoidResult::ok(),
|
||||||
Err(e) => WasmVoidResult::err(e, &env),
|
Err(e) => WasmVoidResult::err(e, &env),
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue