use anyhow::Result;
use battler_data::{
HitEffect,
MonOverride,
};
use crate::{
battle::{
ContextCache,
CoreBattle,
Mon,
MonHandle,
MoveHandle,
Player,
Side,
},
common::{
MaybeOwnedMut,
UnsafelyDetachBorrowMut,
},
effect::{
Effect,
EffectHandle,
},
error::{
WrapOptionError,
general_error,
},
moves::{
Move,
MoveHitEffectType,
},
};
pub struct Context<'battle, 'data>
where
'data: 'battle,
{
battle: &'battle mut CoreBattle<'data>,
cache: ContextCache<'battle>,
}
impl<'battle, 'data> Context<'battle, 'data> {
pub fn new(battle: &'battle mut CoreBattle<'data>) -> Self {
Self {
battle,
cache: ContextCache::new(),
}
}
pub fn side_context<'context>(
&'context mut self,
side: usize,
) -> Result<SideContext<'context, 'battle, 'data>> {
SideContext::new(self.into(), side)
}
pub fn player_context<'context>(
&'context mut self,
player: usize,
) -> Result<PlayerContext<'context, 'context, 'battle, 'data>> {
PlayerContext::new(self.into(), player)
}
pub fn mon_context<'context>(
&'context mut self,
mon_handle: MonHandle,
) -> Result<MonContext<'context, 'context, 'context, 'battle, 'data>> {
MonContext::new(self.into(), mon_handle)
}
pub fn effect_context<'context>(
&'context mut self,
effect_handle: EffectHandle,
source_effect_handle: Option<EffectHandle>,
) -> Result<EffectContext<'context, 'battle, 'data>> {
EffectContext::new(self.into(), effect_handle, source_effect_handle)
}
pub fn applying_effect_context<'context>(
&'context mut self,
effect_handle: EffectHandle,
source_handle: Option<MonHandle>,
target_handle: MonHandle,
source_effect_handle: Option<EffectHandle>,
) -> Result<ApplyingEffectContext<'context, 'context, 'battle, 'data>> {
ApplyingEffectContext::new(
self.effect_context(effect_handle, source_effect_handle)?
.into(),
source_handle,
target_handle,
)
}
pub fn side_effect_context<'context>(
&'context mut self,
effect_handle: EffectHandle,
side: usize,
source_handle: Option<MonHandle>,
source_effect_handle: Option<EffectHandle>,
) -> Result<SideEffectContext<'context, 'context, 'battle, 'data>> {
SideEffectContext::new(
self.effect_context(effect_handle, source_effect_handle)?
.into(),
side,
source_handle,
)
}
pub fn player_effect_context<'context>(
&'context mut self,
effect_handle: EffectHandle,
player: usize,
source_handle: Option<MonHandle>,
source_effect_handle: Option<EffectHandle>,
) -> Result<PlayerEffectContext<'context, 'context, 'battle, 'data>> {
PlayerEffectContext::new(
self.effect_context(effect_handle, source_effect_handle)?
.into(),
player,
source_handle,
)
}
pub fn field_effect_context<'context>(
&'context mut self,
effect_handle: EffectHandle,
source_handle: Option<MonHandle>,
source_effect_handle: Option<EffectHandle>,
) -> Result<FieldEffectContext<'context, 'context, 'battle, 'data>> {
FieldEffectContext::new(
self.effect_context(effect_handle, source_effect_handle)?
.into(),
source_handle,
)
}
pub fn active_move_context<'context>(
&'context mut self,
active_move_handle: MoveHandle,
hit_effect_type: MoveHitEffectType,
) -> Result<ActiveMoveContext<'context, 'context, 'context, 'context, 'battle, 'data>> {
let user = self
.active_move(active_move_handle)?
.used_by
.wrap_expectation("active move handle does not have a user")?;
ActiveMoveContext::new_from_mon_context(
self.mon_context(user)?.into(),
active_move_handle,
hit_effect_type,
)
}
pub fn battle(&self) -> &CoreBattle<'data> {
self.battle
}
pub fn battle_mut(&mut self) -> &mut CoreBattle<'data> {
self.battle
}
pub fn mon(&self, mon_handle: MonHandle) -> Result<&Mon> {
self.cache.mon(self.battle(), mon_handle).map(|mon| &*mon)
}
pub fn mon_mut(&mut self, mon_handle: MonHandle) -> Result<&mut Mon> {
self.cache.mon(self.battle(), mon_handle)
}
pub fn active_move(&self, active_move_handle: MoveHandle) -> Result<&Move> {
self.cache
.active_move(self.battle(), active_move_handle)
.map(|mov| &*mov)
}
pub fn active_move_mut(&self, active_move_handle: MoveHandle) -> Result<&mut Move> {
self.cache.active_move(self.battle(), active_move_handle)
}
pub fn clear_context_cache(&mut self) {
self.cache.clear();
}
}
impl<'battle, 'data> Drop for Context<'battle, 'data> {
fn drop(&mut self) {}
}
pub struct SideContext<'context, 'battle, 'data>
where
'data: 'battle,
'battle: 'context,
{
context: MaybeOwnedMut<'context, Context<'battle, 'data>>,
side: *mut Side,
foe_side: *mut Side,
}
impl<'context, 'battle, 'data> SideContext<'context, 'battle, 'data> {
fn new(
mut context: MaybeOwnedMut<'context, Context<'battle, 'data>>,
side: usize,
) -> Result<Self> {
let foe_side = side ^ 1;
let side = unsafe {
core::mem::transmute::<&mut Side, &mut Side>(&mut *context.battle_mut().side_mut(side)?)
};
let foe_side = unsafe {
core::mem::transmute::<&mut Side, &mut Side>(
&mut *context.battle_mut().side_mut(foe_side)?,
)
};
Ok(Self {
context: context.into(),
side,
foe_side,
})
}
pub fn as_battle_context<'side>(&'side self) -> &'side Context<'battle, 'data> {
&self.context
}
pub fn as_battle_context_mut<'side>(&'side mut self) -> &'side mut Context<'battle, 'data> {
&mut self.context
}
pub fn foe_side_context<'side>(&'side mut self) -> Result<SideContext<'side, 'battle, 'data>> {
let foe_side = self.foe_side().index;
self.as_battle_context_mut().side_context(foe_side)
}
pub fn player_context<'side>(
&'side mut self,
position: usize,
) -> Result<PlayerContext<'side, 'context, 'battle, 'data>> {
let player = Side::player_position_to_index(self, position)
.wrap_not_found_error_with_format(format_args!("player at position {position}"))?;
PlayerContext::new_from_side_context(self.into(), player)
}
pub fn side_effect_context<'mon>(
&'mon mut self,
effect_handle: EffectHandle,
source: Option<MonHandle>,
source_effect_handle: Option<EffectHandle>,
) -> Result<SideEffectContext<'mon, 'mon, 'battle, 'data>> {
let side = unsafe { &*self.side }.index;
self.as_battle_context_mut().side_effect_context(
effect_handle,
side,
source,
source_effect_handle,
)
}
pub fn battle(&self) -> &CoreBattle<'data> {
self.context.battle()
}
pub fn battle_mut(&mut self) -> &mut CoreBattle<'data> {
self.context.battle_mut()
}
pub fn side(&self) -> &Side {
unsafe { &*self.side }
}
pub fn side_mut(&mut self) -> &mut Side {
unsafe { &mut *self.side }
}
pub fn foe_side(&self) -> &Side {
unsafe { &*self.foe_side }
}
pub fn foe_side_mut(&mut self) -> &mut Side {
unsafe { &mut *self.foe_side }
}
pub fn mon(&self, mon_handle: MonHandle) -> Result<&Mon> {
self.context.mon(mon_handle)
}
pub fn mon_mut(&mut self, mon_handle: MonHandle) -> Result<&mut Mon> {
self.context.mon_mut(mon_handle)
}
}
pub struct PlayerContext<'side, 'context, 'battle, 'data>
where
'data: 'battle,
'battle: 'context,
'context: 'side,
{
context: MaybeOwnedMut<'side, SideContext<'context, 'battle, 'data>>,
player: *mut Player,
}
impl<'side, 'context, 'battle, 'data> PlayerContext<'side, 'context, 'battle, 'data> {
fn new(
mut context: MaybeOwnedMut<'context, Context<'battle, 'data>>,
player: usize,
) -> Result<Self> {
let player = unsafe {
core::mem::transmute::<&mut Player, &mut Player>(
&mut *context.battle_mut().player_mut(player)?,
)
};
let context = SideContext::new(context, player.side)?;
Ok(Self {
context: context.into(),
player,
})
}
fn new_from_side_context(
mut context: MaybeOwnedMut<'side, SideContext<'context, 'battle, 'data>>,
player: usize,
) -> Result<Self> {
let player = &mut *context.battle_mut().player_mut(player)?;
let player = unsafe { player.unsafely_detach_borrow_mut() };
Ok(Self {
context: context.into(),
player,
})
}
pub fn as_battle_context<'player>(&'player self) -> &'player Context<'battle, 'data> {
self.context.as_battle_context()
}
pub fn as_battle_context_mut<'player>(
&'player mut self,
) -> &'player mut Context<'battle, 'data> {
self.context.as_battle_context_mut()
}
pub fn as_side_context<'player>(
&'player self,
) -> &'player SideContext<'context, 'battle, 'data> {
&self.context
}
pub fn as_side_context_mut<'player>(
&'player mut self,
) -> &'player mut SideContext<'context, 'battle, 'data> {
&mut self.context
}
pub fn foe_side_context<'player>(
&'player mut self,
) -> Result<SideContext<'player, 'battle, 'data>> {
let foe_side = self.foe_side().index;
self.as_battle_context_mut().side_context(foe_side)
}
pub fn pick_side_context<'player>(
&'player mut self,
same_side: bool,
) -> Result<SideContext<'player, 'battle, 'data>> {
if same_side {
let side = self.side().index;
self.as_battle_context_mut().side_context(side)
} else {
Ok(self.foe_side_context()?.into())
}
}
pub fn mon_context<'player>(
&'player mut self,
mon_handle: MonHandle,
) -> Result<MonContext<'player, 'side, 'context, 'battle, 'data>> {
MonContext::new_from_player_context(self, mon_handle)
}
pub fn player_effect_context<'mon>(
&'mon mut self,
effect_handle: EffectHandle,
source: Option<MonHandle>,
source_effect_handle: Option<EffectHandle>,
) -> Result<PlayerEffectContext<'mon, 'mon, 'battle, 'data>> {
let player = unsafe { &*self.player }.index;
self.as_battle_context_mut().player_effect_context(
effect_handle,
player,
source,
source_effect_handle,
)
}
pub fn battle(&self) -> &CoreBattle<'data> {
self.context.battle()
}
pub fn battle_mut(&mut self) -> &mut CoreBattle<'data> {
self.context.battle_mut()
}
pub fn side(&self) -> &Side {
self.context.side()
}
pub fn side_mut(&mut self) -> &mut Side {
self.context.side_mut()
}
pub fn foe_side(&self) -> &Side {
self.context.foe_side()
}
pub fn foe_side_mut(&mut self) -> &mut Side {
self.context.foe_side_mut()
}
pub fn player(&self) -> &Player {
unsafe { &*self.player }
}
pub fn player_mut(&mut self) -> &mut Player {
unsafe { &mut *self.player }
}
pub fn mon(&self, mon_handle: MonHandle) -> Result<&Mon> {
self.context.mon(mon_handle)
}
pub fn mon_mut(&mut self, mon_handle: MonHandle) -> Result<&mut Mon> {
self.context.mon_mut(mon_handle)
}
}
pub struct MonContext<'player, 'side, 'context, 'battle, 'data>
where
'data: 'battle,
'battle: 'context,
'context: 'side,
'side: 'player,
{
context: MaybeOwnedMut<'player, PlayerContext<'side, 'context, 'battle, 'data>>,
mon_handle: MonHandle,
mon: &'context mut Mon,
}
impl<'player, 'side, 'context, 'battle, 'data>
MonContext<'player, 'side, 'context, 'battle, 'data>
{
fn new(
context: MaybeOwnedMut<'context, Context<'battle, 'data>>,
mon_handle: MonHandle,
) -> Result<Self> {
let player = context.cache.mon(context.battle(), mon_handle)?.player;
let context = PlayerContext::new(context, player)?;
let mon = context
.as_battle_context()
.cache
.mon(context.battle(), mon_handle)?;
let mon = unsafe { mon.unsafely_detach_borrow_mut() };
Ok(Self {
context: context.into(),
mon_handle,
mon,
})
}
fn new_from_player_context(
player_context: &'player mut PlayerContext<'side, 'context, 'battle, 'data>,
mon_handle: MonHandle,
) -> Result<Self> {
let mon = player_context
.as_battle_context()
.cache
.mon(player_context.battle(), mon_handle)?;
let mon = unsafe { mon.unsafely_detach_borrow_mut() };
Ok(Self {
context: player_context.into(),
mon_handle,
mon,
})
}
fn new_from_mon_ref(
player_context: PlayerContext<'side, 'context, 'battle, 'data>,
mon_handle: MonHandle,
mon: &'context mut Mon,
) -> Self {
Self {
context: player_context.into(),
mon_handle,
mon,
}
}
pub fn as_battle_context<'mon>(&'mon self) -> &'mon Context<'battle, 'data> {
self.context.as_battle_context()
}
pub fn as_battle_context_mut<'mon>(&'mon mut self) -> &'mon mut Context<'battle, 'data> {
self.context.as_battle_context_mut()
}
pub fn as_side_context<'mon>(&'mon self) -> &'mon SideContext<'side, 'battle, 'data> {
self.context.as_side_context()
}
pub fn as_side_context_mut<'mon>(
&'mon mut self,
) -> &'mon mut SideContext<'context, 'battle, 'data> {
self.context.as_side_context_mut()
}
pub fn foe_side_context<'mon>(&'mon mut self) -> Result<SideContext<'mon, 'battle, 'data>> {
self.context.foe_side_context()
}
pub fn pick_side_context<'mon>(
&'mon mut self,
same_side: bool,
) -> Result<SideContext<'mon, 'battle, 'data>> {
self.context.pick_side_context(same_side)
}
pub fn as_player_context<'mon>(
&'mon self,
) -> &'mon PlayerContext<'side, 'context, 'battle, 'data> {
&self.context
}
pub fn as_player_context_mut<'mon>(
&'mon mut self,
) -> &'mon mut PlayerContext<'side, 'context, 'battle, 'data> {
&mut self.context
}
pub fn active_move_context<'mon>(
&'mon mut self,
active_move_handle: MoveHandle,
) -> Result<ActiveMoveContext<'mon, 'player, 'side, 'context, 'battle, 'data>> {
ActiveMoveContext::new_from_mon_context(
self.into(),
active_move_handle,
MoveHitEffectType::PrimaryEffect,
)
}
pub fn applying_effect_context<'mon>(
&'mon mut self,
effect_handle: EffectHandle,
source: Option<MonHandle>,
source_effect_handle: Option<EffectHandle>,
) -> Result<ApplyingEffectContext<'mon, 'mon, 'battle, 'data>> {
let mon_handle = self.mon_handle;
self.as_battle_context_mut().applying_effect_context(
effect_handle,
source,
mon_handle,
source_effect_handle,
)
}
pub fn battle(&self) -> &CoreBattle<'data> {
self.context.battle()
}
pub fn battle_mut(&mut self) -> &mut CoreBattle<'data> {
self.context.battle_mut()
}
pub fn side(&self) -> &Side {
self.context.side()
}
pub fn side_mut(&mut self) -> &mut Side {
self.context.side_mut()
}
pub fn foe_side(&self) -> &Side {
self.context.foe_side()
}
pub fn foe_side_mut(&mut self) -> &mut Side {
self.context.foe_side_mut()
}
pub fn player(&self) -> &Player {
self.context.player()
}
pub fn player_mut(&mut self) -> &mut Player {
self.context.player_mut()
}
pub fn mon_handle(&self) -> MonHandle {
self.mon_handle
}
pub fn mon(&self) -> &Mon {
&*self.mon
}
pub fn mon_mut(&mut self) -> &mut Mon {
&mut *self.mon
}
}
pub struct ActiveMoveContext<'mon, 'player, 'side, 'context, 'battle, 'data>
where
'data: 'battle,
'battle: 'context,
'context: 'side,
'side: 'player,
'player: 'mon,
{
context: MaybeOwnedMut<'mon, MonContext<'player, 'side, 'context, 'battle, 'data>>,
active_move_handle: MoveHandle,
active_move: &'context mut Move,
hit_effect_type: MoveHitEffectType,
is_self: bool,
is_external: bool,
}
impl<'mon, 'player, 'side, 'context, 'battle, 'data>
ActiveMoveContext<'mon, 'player, 'side, 'context, 'battle, 'data>
{
fn new_from_mon_context(
context: MaybeOwnedMut<'mon, MonContext<'player, 'side, 'context, 'battle, 'data>>,
active_move_handle: MoveHandle,
hit_effect_type: MoveHitEffectType,
) -> Result<Self> {
let active_move = context
.as_battle_context()
.cache
.active_move(context.battle(), active_move_handle)?;
let active_move = unsafe { active_move.unsafely_detach_borrow_mut() };
Ok(Self {
context,
active_move_handle,
active_move,
hit_effect_type,
is_self: false,
is_external: false,
})
}
fn new_from_active_move_context(
context: &mut Self,
hit_effect_type: MoveHitEffectType,
is_self: bool,
is_external: bool,
) -> Self {
let active_move_handle = context.active_move_handle.clone();
let active_move = &mut *context.active_move;
let active_move = unsafe { active_move.unsafely_detach_borrow_mut() };
let context = context.as_mon_context_mut();
let context = unsafe { context.unsafely_detach_borrow_mut() };
let context = context.into();
Self {
context,
active_move_handle,
active_move,
hit_effect_type,
is_self,
is_external,
}
}
fn new_from_move_handle(
context: &'context mut Context<'battle, 'data>,
active_move_handle: MoveHandle,
hit_effect_type: MoveHitEffectType,
) -> Result<Self>
where
'side: 'context,
{
let active_move = context
.cache
.active_move(context.battle(), active_move_handle)?;
let active_move = unsafe { active_move.unsafely_detach_borrow_mut() };
let mon_handle = active_move
.used_by
.wrap_expectation_with_format(format_args!(
"active move {active_move_handle} does not have an associated mon"
))?;
let context = context.mon_context(mon_handle)?;
Ok(Self {
context: MaybeOwnedMut::Owned(context),
active_move_handle,
active_move,
hit_effect_type,
is_self: false,
is_external: false,
})
}
pub fn as_battle_context<'active_move>(
&'active_move self,
) -> &'active_move Context<'battle, 'data> {
self.context.as_battle_context()
}
pub fn as_battle_context_mut<'active_move>(
&'active_move mut self,
) -> &'active_move mut Context<'battle, 'data> {
self.context.as_battle_context_mut()
}
pub fn as_side_context<'active_move>(
&'active_move self,
) -> &'active_move SideContext<'side, 'battle, 'data> {
self.context.as_side_context()
}
pub fn as_side_context_mut<'active_move>(
&'active_move mut self,
) -> &'active_move mut SideContext<'context, 'battle, 'data> {
self.context.as_side_context_mut()
}
pub fn foe_side_context<'active_move>(
&'active_move mut self,
) -> Result<SideContext<'active_move, 'battle, 'data>> {
self.context.foe_side_context()
}
pub fn as_player_context<'active_move>(
&'active_move self,
) -> &'active_move PlayerContext<'side, 'context, 'battle, 'data> {
self.context.as_player_context()
}
pub fn as_player_context_mut<'active_move>(
&'active_move mut self,
) -> &'active_move mut PlayerContext<'side, 'context, 'battle, 'data> {
self.context.as_player_context_mut()
}
pub fn as_mon_context<'active_move>(
&'active_move self,
) -> &'active_move MonContext<'player, 'side, 'context, 'battle, 'data> {
&self.context
}
pub fn as_mon_context_mut<'active_move>(
&'active_move mut self,
) -> &'active_move mut MonContext<'player, 'side, 'context, 'battle, 'data> {
&mut self.context
}
pub fn target_mon_context<'active_move>(
&'active_move mut self,
target_mon_handle: MonHandle,
) -> Result<MonContext<'active_move, 'active_move, 'active_move, 'battle, 'data>> {
let mon = self
.as_battle_context()
.cache
.mon(self.battle(), target_mon_handle)?;
let mon = unsafe { mon.unsafely_detach_borrow_mut() };
let player_context = self.as_battle_context_mut().player_context(mon.player)?;
Ok(MonContext::new_from_mon_ref(
player_context,
target_mon_handle,
mon,
))
}
pub fn target_context<'active_move>(
&'active_move mut self,
target_mon_handle: MonHandle,
) -> Result<ActiveTargetContext<'active_move, 'mon, 'player, 'side, 'context, 'battle, 'data>>
{
ActiveTargetContext::new_from_active_move_context(self.into(), target_mon_handle)
}
pub fn effect_context<'active_move>(
&'active_move mut self,
) -> Result<EffectContext<'active_move, 'battle, 'data>> {
let effect_handle = self.effect_handle();
let source_effect_handle = self.source_effect_handle();
self.as_battle_context_mut()
.effect_context(effect_handle, source_effect_handle)
}
pub fn applying_effect_context_for_target<'active_move>(
&'active_move mut self,
target_handle: MonHandle,
) -> Result<ApplyingEffectContext<'active_move, 'active_move, 'battle, 'data>> {
let source_handle = self.mon_handle();
ApplyingEffectContext::new(
self.effect_context()?.into(),
Some(source_handle),
target_handle,
)
}
pub fn side_effect_context<'active_move>(
&'active_move mut self,
side: usize,
) -> Result<SideEffectContext<'active_move, 'active_move, 'battle, 'data>> {
let source_handle = self.mon_handle();
SideEffectContext::new(self.effect_context()?.into(), side, Some(source_handle))
}
pub fn field_effect_context<'active_move>(
&'active_move mut self,
) -> Result<FieldEffectContext<'active_move, 'active_move, 'battle, 'data>> {
let source_handle = self.mon_handle();
FieldEffectContext::new(self.effect_context()?.into(), Some(source_handle))
}
pub fn user_applying_effect_context<'active_move>(
&'active_move mut self,
target_handle: Option<MonHandle>,
) -> Result<ApplyingEffectContext<'active_move, 'active_move, 'battle, 'data>> {
let user_handle = self.mon_handle();
ApplyingEffectContext::new(self.effect_context()?.into(), target_handle, user_handle)
}
pub fn secondary_active_move_context(&mut self, target: MonHandle, index: usize) -> Self {
ActiveMoveContext::new_from_active_move_context(
self,
MoveHitEffectType::SecondaryEffect(target, self.active_move.hit, index),
self.is_self,
self.is_external,
)
}
pub fn hit_self_active_move_context(&mut self) -> Self {
ActiveMoveContext::new_from_active_move_context(
self,
self.hit_effect_type,
true,
self.is_external,
)
}
pub fn battle(&self) -> &CoreBattle<'data> {
self.context.battle()
}
pub fn battle_mut(&mut self) -> &mut CoreBattle<'data> {
self.context.battle_mut()
}
pub fn side(&self) -> &Side {
self.context.side()
}
pub fn side_mut(&mut self) -> &mut Side {
self.context.side_mut()
}
pub fn foe_side(&self) -> &Side {
self.context.foe_side()
}
pub fn foe_side_mut(&mut self) -> &mut Side {
self.context.foe_side_mut()
}
pub fn player(&self) -> &Player {
self.context.player()
}
pub fn player_mut(&mut self) -> &mut Player {
self.context.player_mut()
}
pub fn mon_handle(&self) -> MonHandle {
self.context.mon_handle()
}
pub fn mon(&self) -> &Mon {
self.context.mon()
}
pub fn mon_mut(&mut self) -> &mut Mon {
self.context.mon_mut()
}
pub fn effect_handle(&self) -> EffectHandle {
EffectHandle::ActiveMove(self.active_move_handle, self.hit_effect_type)
}
pub fn source_effect_handle(&self) -> Option<EffectHandle> {
self.active_move.effect_state.source_effect()
}
pub fn active_move_handle(&self) -> MoveHandle {
self.active_move_handle
}
pub fn active_move(&self) -> &Move {
&*self.active_move
}
pub fn active_move_mut(&mut self) -> &mut Move {
&mut *self.active_move
}
pub fn is_primary(&self) -> bool {
match self.hit_effect_type {
MoveHitEffectType::PrimaryEffect => true,
_ => false,
}
}
pub fn is_secondary(&self) -> bool {
match self.hit_effect_type {
MoveHitEffectType::SecondaryEffect(_, _, _) => true,
_ => false,
}
}
pub fn is_self(&self) -> bool {
self.is_self
}
pub fn is_external(&self) -> bool {
self.is_external
}
pub fn hit_effect_type(&self) -> MoveHitEffectType {
self.hit_effect_type
}
pub fn hit_effect(&self) -> Option<&HitEffect> {
if self.is_self {
self.active_move.user_hit_effect(self.hit_effect_type)
} else {
self.active_move.target_hit_effect(self.hit_effect_type)
}
}
pub fn hit_effect_mut(&mut self) -> Option<&mut HitEffect> {
if self.is_self {
self.active_move.user_hit_effect_mut(self.hit_effect_type)
} else {
self.active_move.target_hit_effect_mut(self.hit_effect_type)
}
}
}
pub struct ActiveTargetContext<'active_move, 'mon, 'player, 'side, 'context, 'battle, 'data>
where
'data: 'battle,
'battle: 'context,
'context: 'side,
'side: 'player,
'mon: 'active_move,
{
context: MaybeOwnedMut<
'active_move,
ActiveMoveContext<'mon, 'player, 'side, 'context, 'battle, 'data>,
>,
active_target_handle: MonHandle,
active_target: &'context mut Mon,
}
impl<'active_move, 'mon, 'player, 'side, 'context, 'battle, 'data>
ActiveTargetContext<'active_move, 'mon, 'player, 'side, 'context, 'battle, 'data>
{
fn new_from_active_move_context(
context: MaybeOwnedMut<
'active_move,
ActiveMoveContext<'mon, 'player, 'side, 'context, 'battle, 'data>,
>,
active_target_handle: MonHandle,
) -> Result<Self> {
let active_target = context
.as_battle_context()
.cache
.mon(context.battle(), active_target_handle)?;
let active_target = unsafe { active_target.unsafely_detach_borrow_mut() };
Ok(Self {
context,
active_target_handle,
active_target,
})
}
pub fn as_battle_context<'active_target>(
&'active_target self,
) -> &'active_target Context<'battle, 'data> {
self.context.as_battle_context()
}
pub fn as_battle_context_mut<'active_target>(
&'active_target mut self,
) -> &'active_target mut Context<'battle, 'data> {
self.context.as_battle_context_mut()
}
pub fn as_side_context<'active_target>(
&'active_target self,
) -> &'active_target SideContext<'side, 'battle, 'data> {
self.context.as_side_context()
}
pub fn as_side_context_mut<'active_target>(
&'active_target mut self,
) -> &'active_target mut SideContext<'context, 'battle, 'data> {
self.context.as_side_context_mut()
}
pub fn foe_side_context<'active_target>(
&'active_target mut self,
) -> Result<SideContext<'active_target, 'battle, 'data>> {
self.context.foe_side_context()
}
pub fn as_player_context<'active_target>(
&'active_target self,
) -> &'active_target PlayerContext<'side, 'context, 'battle, 'data> {
self.context.as_player_context()
}
pub fn as_player_context_mut<'active_target>(
&'active_target mut self,
) -> &'active_target mut PlayerContext<'side, 'context, 'battle, 'data> {
self.context.as_player_context_mut()
}
pub fn as_mon_context<'active_target>(
&'active_target self,
) -> &'active_target MonContext<'player, 'side, 'context, 'battle, 'data> {
self.context.as_mon_context()
}
pub fn as_mon_context_mut<'active_target>(
&'active_target mut self,
) -> &'active_target mut MonContext<'player, 'side, 'context, 'battle, 'data> {
self.context.as_mon_context_mut()
}
pub fn as_active_move_context<'active_target>(
&'active_target self,
) -> &'active_target ActiveMoveContext<'mon, 'player, 'side, 'context, 'battle, 'data> {
&self.context
}
pub fn as_active_move_context_mut<'active_target>(
&'active_target mut self,
) -> &'active_target mut ActiveMoveContext<'mon, 'player, 'side, 'context, 'battle, 'data> {
&mut self.context
}
pub fn target_mon_context<'active_target>(
&'active_target mut self,
) -> Result<MonContext<'active_target, 'active_target, 'active_target, 'battle, 'data>> {
let target_handle = self.target_mon_handle();
self.as_battle_context_mut().mon_context(target_handle)
}
pub fn attacker_context<'active_target>(
&'active_target mut self,
) -> Result<MonContext<'active_target, 'active_target, 'active_target, 'battle, 'data>> {
match self.active_move().data.override_offensive_mon {
Some(MonOverride::Target) => self.target_mon_context(),
_ => {
let mon_handle = self.mon_handle();
self.as_battle_context_mut().mon_context(mon_handle)
}
}
}
pub fn defender_context<'active_target>(
&'active_target mut self,
) -> Result<MonContext<'active_target, 'active_target, 'active_target, 'battle, 'data>> {
match self.active_move().data.override_defensive_mon {
Some(MonOverride::User) => {
let mon_handle = self.mon_handle();
self.as_battle_context_mut().mon_context(mon_handle)
}
_ => self.target_mon_context(),
}
}
pub fn applying_effect_context<'active_target>(
&'active_target mut self,
) -> Result<ApplyingEffectContext<'active_target, 'active_target, 'battle, 'data>> {
let source_handle = self.mon_handle();
let target_handle = self.target_mon_handle();
ApplyingEffectContext::new(
self.as_active_move_context_mut().effect_context()?.into(),
Some(source_handle),
target_handle,
)
}
pub fn user_applying_effect_context<'active_target>(
&'active_target mut self,
) -> Result<ApplyingEffectContext<'active_target, 'active_target, 'battle, 'data>> {
let source_handle = self.target_mon_handle();
let target_handle = self.mon_handle();
ApplyingEffectContext::new(
self.as_active_move_context_mut().effect_context()?.into(),
Some(source_handle),
target_handle,
)
}
pub fn battle(&self) -> &CoreBattle<'data> {
self.context.battle()
}
pub fn battle_mut(&mut self) -> &mut CoreBattle<'data> {
self.context.battle_mut()
}
pub fn side(&self) -> &Side {
self.context.side()
}
pub fn side_mut(&mut self) -> &mut Side {
self.context.side_mut()
}
pub fn foe_side(&self) -> &Side {
self.context.foe_side()
}
pub fn foe_side_mut(&mut self) -> &mut Side {
self.context.foe_side_mut()
}
pub fn player(&self) -> &Player {
self.context.player()
}
pub fn player_mut(&mut self) -> &mut Player {
self.context.player_mut()
}
pub fn mon_handle(&self) -> MonHandle {
self.context.mon_handle()
}
pub fn mon(&self) -> &Mon {
self.context.mon()
}
pub fn mon_mut(&mut self) -> &mut Mon {
self.context.mon_mut()
}
pub fn effect_handle(&self) -> EffectHandle {
self.context.effect_handle()
}
pub fn active_move_handle(&self) -> MoveHandle {
self.context.active_move_handle()
}
pub fn active_move(&self) -> &Move {
self.context.active_move()
}
pub fn active_move_mut(&mut self) -> &mut Move {
self.context.active_move_mut()
}
pub fn source_effect_handle(&mut self) -> Option<EffectHandle> {
self.context.source_effect_handle()
}
pub fn is_primary(&self) -> bool {
self.context.is_primary()
}
pub fn is_secondary(&self) -> bool {
self.context.is_secondary()
}
pub fn is_self(&self) -> bool {
self.context.is_self()
}
pub fn is_external(&self) -> bool {
self.context.is_external()
}
pub fn hit_effect(&self) -> Option<&HitEffect> {
self.context.hit_effect()
}
pub fn hit_effect_mut(&mut self) -> Option<&mut HitEffect> {
self.context.hit_effect_mut()
}
pub fn target_mon_handle(&self) -> MonHandle {
self.active_target_handle
}
pub fn target_mon(&self) -> &Mon {
&self.active_target
}
pub fn target_mon_mut(&mut self) -> &mut Mon {
&mut self.active_target
}
}
pub struct EffectContext<'context, 'battle, 'data>
where
'data: 'battle,
'battle: 'context,
{
context: MaybeOwnedMut<'context, Context<'battle, 'data>>,
effect: Effect<'context>,
effect_handle: EffectHandle,
source_effect_handle: Option<EffectHandle>,
}
impl<'context, 'battle, 'data> EffectContext<'context, 'battle, 'data> {
fn new(
context: MaybeOwnedMut<'context, Context<'battle, 'data>>,
effect_handle: EffectHandle,
source_effect_handle: Option<EffectHandle>,
) -> Result<Self> {
let effect = CoreBattle::get_effect_by_handle(context.as_ref(), &effect_handle)?;
let effect: Effect =
unsafe { core::mem::transmute::<Effect<'_>, Effect<'context>>(effect) };
Ok(Self {
context,
effect,
effect_handle,
source_effect_handle,
})
}
pub fn as_battle_context<'effect>(&'effect self) -> &'effect Context<'battle, 'data> {
&self.context
}
pub fn as_battle_context_mut<'effect>(
&'effect mut self,
) -> &'effect mut Context<'battle, 'data> {
&mut self.context
}
pub fn applying_effect_context<'effect>(
&'effect mut self,
source_handle: Option<MonHandle>,
target_handle: MonHandle,
) -> Result<ApplyingEffectContext<'effect, 'context, 'battle, 'data>> {
ApplyingEffectContext::new(self.into(), source_handle, target_handle)
}
pub fn player_effect_context<'effect>(
&'effect mut self,
player: usize,
source_handle: Option<MonHandle>,
) -> Result<PlayerEffectContext<'effect, 'context, 'battle, 'data>> {
PlayerEffectContext::new(self.into(), player, source_handle)
}
pub fn side_effect_context<'effect>(
&'effect mut self,
side: usize,
source_handle: Option<MonHandle>,
) -> Result<SideEffectContext<'effect, 'context, 'battle, 'data>> {
SideEffectContext::new(self.into(), side, source_handle)
}
pub fn field_effect_context<'effect>(
&'effect mut self,
source_handle: Option<MonHandle>,
) -> Result<FieldEffectContext<'effect, 'context, 'battle, 'data>> {
FieldEffectContext::new(self.into(), source_handle)
}
pub fn active_move_context<'effect>(
&'effect mut self,
) -> Result<ActiveMoveContext<'effect, 'effect, 'effect, 'effect, 'battle, 'data>> {
match self.effect_handle {
EffectHandle::ActiveMove(active_move_handle, hit_effect_type) => {
ActiveMoveContext::new_from_move_handle(
self.context.as_mut(),
active_move_handle,
hit_effect_type,
)
}
_ => Err(general_error(
"effect context does not contain an active move",
)),
}
}
pub fn source_effect_context<'effect>(
&'effect mut self,
) -> Result<Option<EffectContext<'effect, 'battle, 'data>>> {
match self.source_effect_handle.clone() {
Some(effect_handle) => Ok(Some(EffectContext::new(
self.context.as_mut().into(),
effect_handle,
None,
)?)),
None => Ok(None),
}
}
pub fn source_active_move_context<'effect>(
&'effect mut self,
) -> Result<Option<ActiveMoveContext<'effect, 'effect, 'effect, 'effect, 'battle, 'data>>> {
match self.source_effect_handle.clone() {
Some(EffectHandle::ActiveMove(active_move_handle, hit_effect_type)) => {
Ok(Some(ActiveMoveContext::new_from_move_handle(
self.context.as_mut(),
active_move_handle,
hit_effect_type,
)?))
}
_ => Ok(None),
}
}
pub fn forward_effect_context<'effect>(
&'effect mut self,
effect_handle: EffectHandle,
) -> Result<EffectContext<'effect, 'battle, 'data>> {
let source_effect_handle = self.effect_handle.clone();
self.as_battle_context_mut()
.effect_context(effect_handle, Some(source_effect_handle))
}
pub fn battle(&self) -> &CoreBattle<'data> {
self.context.battle()
}
pub fn battle_mut(&mut self) -> &mut CoreBattle<'data> {
self.context.battle_mut()
}
pub fn effect_handle(&self) -> &EffectHandle {
&self.effect_handle
}
pub fn effect(&self) -> &Effect<'_> {
&self.effect
}
pub fn effect_mut(&mut self) -> &mut Effect<'context> {
&mut self.effect
}
pub fn source_effect_handle(&self) -> Option<&EffectHandle> {
self.source_effect_handle.as_ref()
}
}
pub struct ApplyingEffectContext<'effect, 'context, 'battle, 'data>
where
'data: 'battle,
'battle: 'context,
'context: 'effect,
{
context: MaybeOwnedMut<'effect, EffectContext<'context, 'battle, 'data>>,
source_handle: Option<MonHandle>,
source: Option<&'context mut Mon>,
target_handle: MonHandle,
target: &'context mut Mon,
}
impl<'effect, 'context, 'battle, 'data> ApplyingEffectContext<'effect, 'context, 'battle, 'data> {
fn new(
context: MaybeOwnedMut<'effect, EffectContext<'context, 'battle, 'data>>,
source_handle: Option<MonHandle>,
target_handle: MonHandle,
) -> Result<Self> {
let target = context
.as_battle_context()
.cache
.mon(context.battle(), target_handle)?;
let target = unsafe { target.unsafely_detach_borrow_mut() };
let source = match source_handle {
None => None,
Some(source_handle) => {
let source = context
.as_battle_context()
.cache
.mon(context.battle(), source_handle)?;
let source = unsafe { source.unsafely_detach_borrow_mut() };
Some(source)
}
};
Ok(Self {
context,
source_handle,
source,
target_handle,
target,
})
}
pub fn as_battle_context<'applying_effect>(
&'applying_effect self,
) -> &'applying_effect Context<'battle, 'data> {
self.context.as_battle_context()
}
pub fn as_battle_context_mut<'applying_effect>(
&'applying_effect mut self,
) -> &'applying_effect mut Context<'battle, 'data> {
self.context.as_battle_context_mut()
}
pub fn as_effect_context<'applying_effect>(
&'applying_effect self,
) -> &'applying_effect EffectContext<'context, 'battle, 'data> {
&self.context
}
pub fn as_effect_context_mut<'applying_effect>(
&'applying_effect mut self,
) -> &'applying_effect mut EffectContext<'context, 'battle, 'data> {
&mut self.context
}
pub fn source_context<'applying_effect>(
&'applying_effect mut self,
) -> Result<
Option<MonContext<'applying_effect, 'applying_effect, 'applying_effect, 'battle, 'data>>,
> {
match self.source_handle {
None => Ok(None),
Some(source_handle) => self
.as_battle_context_mut()
.mon_context(source_handle)
.map(|mon_context| Some(mon_context)),
}
}
pub fn target_context<'applying_effect>(
&'applying_effect mut self,
) -> Result<MonContext<'applying_effect, 'applying_effect, 'applying_effect, 'battle, 'data>>
{
let target_handle = self.target_handle;
self.as_battle_context_mut().mon_context(target_handle)
}
pub fn change_target_context<'applying_effect>(
&'applying_effect mut self,
target_handle: MonHandle,
) -> Result<ApplyingEffectContext<'applying_effect, 'context, 'battle, 'data>> {
let source_handle = self.source_handle;
self.as_effect_context_mut()
.applying_effect_context(source_handle, target_handle)
}
pub fn forward_applying_effect_context<'applying_effect>(
&'applying_effect mut self,
effect_handle: EffectHandle,
) -> Result<ApplyingEffectContext<'applying_effect, 'applying_effect, 'battle, 'data>> {
let source_handle = self.source_handle;
let target_handle = self.target_handle;
let source_effect_handle = self.effect_handle().clone();
self.as_battle_context_mut().applying_effect_context(
effect_handle,
source_handle,
target_handle,
Some(source_effect_handle),
)
}
pub fn source_applying_effect_context<'applying_effect>(
&'applying_effect mut self,
) -> Result<Option<ApplyingEffectContext<'applying_effect, 'applying_effect, 'battle, 'data>>>
{
match self.source_effect_handle().cloned() {
Some(source_effect_handle) => {
let source_handle = self.source_handle;
let target_handle = self.target_handle;
Ok(Some(self.as_battle_context_mut().applying_effect_context(
source_effect_handle,
source_handle,
target_handle,
None,
)?))
}
None => Ok(None),
}
}
pub fn active_move_context<'applying_effect>(
&'applying_effect mut self,
) -> Result<
Option<
ActiveMoveContext<
'applying_effect,
'applying_effect,
'applying_effect,
'applying_effect,
'battle,
'data,
>,
>,
> {
match self.effect_handle().clone() {
EffectHandle::ActiveMove(active_move_handle, hit_effect_type) => self
.as_battle_context_mut()
.active_move_context(active_move_handle, hit_effect_type)
.map(|context| Some(context)),
_ => Ok(None),
}
}
pub fn side_effect_context<'applying_effect>(
&'applying_effect mut self,
) -> Result<SideEffectContext<'applying_effect, 'context, 'battle, 'data>> {
let target_side = self.target.side;
let source_handle = self.source_handle;
self.as_effect_context_mut()
.side_effect_context(target_side, source_handle)
}
pub fn field_effect_context<'applying_effect>(
&'applying_effect mut self,
) -> Result<FieldEffectContext<'applying_effect, 'context, 'battle, 'data>> {
let source_handle = self.source_handle;
self.as_effect_context_mut()
.field_effect_context(source_handle)
}
pub fn battle(&self) -> &CoreBattle<'data> {
self.context.battle()
}
pub fn battle_mut(&mut self) -> &mut CoreBattle<'data> {
self.context.battle_mut()
}
pub fn effect_handle(&self) -> &EffectHandle {
self.context.effect_handle()
}
pub fn effect(&self) -> &Effect<'_> {
self.context.effect()
}
pub fn effect_mut(&mut self) -> &mut Effect<'context> {
self.context.effect_mut()
}
pub fn source_effect_handle(&self) -> Option<&EffectHandle> {
self.context.source_effect_handle()
}
pub fn source_handle(&self) -> Option<MonHandle> {
self.source_handle
}
pub fn has_source(&self) -> bool {
self.source.is_some()
}
pub fn source(&self) -> Option<&Mon> {
self.source.as_deref()
}
pub fn source_mut(&mut self) -> Option<&mut Mon> {
self.source.as_deref_mut()
}
pub fn target_handle(&self) -> MonHandle {
self.target_handle
}
pub fn target(&self) -> &Mon {
&self.target
}
pub fn target_mut(&mut self) -> &mut Mon {
&mut self.target
}
}
pub struct PlayerEffectContext<'effect, 'context, 'battle, 'data>
where
'data: 'battle,
'battle: 'context,
'context: 'effect,
{
context: MaybeOwnedMut<'effect, EffectContext<'context, 'battle, 'data>>,
player: *mut Player,
source_handle: Option<MonHandle>,
source: Option<&'context mut Mon>,
}
impl<'effect, 'context, 'battle, 'data> PlayerEffectContext<'effect, 'context, 'battle, 'data> {
fn new(
mut context: MaybeOwnedMut<'effect, EffectContext<'context, 'battle, 'data>>,
player: usize,
source_handle: Option<MonHandle>,
) -> Result<Self> {
let player = unsafe {
core::mem::transmute::<&mut Player, &mut Player>(
&mut *context.battle_mut().player_mut(player)?,
)
};
let source = match source_handle {
None => None,
Some(source_handle) => {
let source = context
.as_battle_context()
.cache
.mon(context.battle(), source_handle)?;
let source = unsafe { source.unsafely_detach_borrow_mut() };
Some(source)
}
};
Ok(Self {
context,
player,
source_handle,
source,
})
}
pub fn as_battle_context<'side_effect>(
&'side_effect self,
) -> &'side_effect Context<'battle, 'data> {
self.context.as_battle_context()
}
pub fn as_battle_context_mut<'side_effect>(
&'side_effect mut self,
) -> &'side_effect mut Context<'battle, 'data> {
self.context.as_battle_context_mut()
}
pub fn as_effect_context<'side_effect>(
&'side_effect self,
) -> &'side_effect EffectContext<'context, 'battle, 'data> {
&self.context
}
pub fn as_effect_context_mut<'side_effect>(
&'side_effect mut self,
) -> &'side_effect mut EffectContext<'context, 'battle, 'data> {
&mut self.context
}
pub fn source_context<'applying_effect>(
&'applying_effect mut self,
) -> Result<
Option<MonContext<'applying_effect, 'applying_effect, 'applying_effect, 'battle, 'data>>,
> {
match self.source_handle {
None => Ok(None),
Some(source_handle) => self
.as_battle_context_mut()
.mon_context(source_handle)
.map(|mon_context| Some(mon_context)),
}
}
pub fn forward_player_effect_context<'side_effect>(
&'side_effect mut self,
effect_handle: EffectHandle,
) -> Result<PlayerEffectContext<'side_effect, 'side_effect, 'battle, 'data>> {
let source_effect_handle = self.effect_handle().clone();
let player = unsafe { &*self.player }.index;
let source_handle = self.source_handle;
self.as_battle_context_mut().player_effect_context(
effect_handle,
player,
source_handle,
Some(source_effect_handle),
)
}
pub fn source_side_effect_context<'side_effect>(
&'side_effect mut self,
) -> Result<Option<SideEffectContext<'side_effect, 'side_effect, 'battle, 'data>>> {
match self.source_effect_handle().cloned() {
Some(source_effect_handle) => {
let player = unsafe { &*self.player }.index;
let source_handle = self.source_handle;
Ok(Some(self.as_battle_context_mut().side_effect_context(
source_effect_handle,
player,
source_handle,
None,
)?))
}
None => Ok(None),
}
}
pub fn battle(&self) -> &CoreBattle<'data> {
self.context.battle()
}
pub fn battle_mut(&mut self) -> &mut CoreBattle<'data> {
self.context.battle_mut()
}
pub fn effect_handle(&self) -> &EffectHandle {
self.context.effect_handle()
}
pub fn effect(&self) -> &Effect<'_> {
self.context.effect()
}
pub fn effect_mut(&mut self) -> &mut Effect<'context> {
self.context.effect_mut()
}
pub fn source_effect_handle(&self) -> Option<&EffectHandle> {
self.context.source_effect_handle()
}
pub fn player(&self) -> &Player {
unsafe { &*self.player }
}
pub fn player_mut(&mut self) -> &mut Player {
unsafe { &mut *self.player }
}
pub fn source_handle(&self) -> Option<MonHandle> {
self.source_handle
}
pub fn has_source(&self) -> bool {
self.source.is_some()
}
pub fn source(&self) -> Option<&Mon> {
self.source.as_deref()
}
pub fn source_mut(&mut self) -> Option<&mut Mon> {
self.source.as_deref_mut()
}
}
pub struct SideEffectContext<'effect, 'context, 'battle, 'data>
where
'data: 'battle,
'battle: 'context,
'context: 'effect,
{
context: MaybeOwnedMut<'effect, EffectContext<'context, 'battle, 'data>>,
side: *mut Side,
source_handle: Option<MonHandle>,
source: Option<&'context mut Mon>,
}
impl<'effect, 'context, 'battle, 'data> SideEffectContext<'effect, 'context, 'battle, 'data> {
fn new(
mut context: MaybeOwnedMut<'effect, EffectContext<'context, 'battle, 'data>>,
side: usize,
source_handle: Option<MonHandle>,
) -> Result<Self> {
let side = unsafe {
core::mem::transmute::<&mut Side, &mut Side>(&mut *context.battle_mut().side_mut(side)?)
};
let source = match source_handle {
None => None,
Some(source_handle) => {
let source = context
.as_battle_context()
.cache
.mon(context.battle(), source_handle)?;
let source = unsafe { source.unsafely_detach_borrow_mut() };
Some(source)
}
};
Ok(Self {
context,
side,
source_handle,
source,
})
}
pub fn as_battle_context<'side_effect>(
&'side_effect self,
) -> &'side_effect Context<'battle, 'data> {
self.context.as_battle_context()
}
pub fn as_battle_context_mut<'side_effect>(
&'side_effect mut self,
) -> &'side_effect mut Context<'battle, 'data> {
self.context.as_battle_context_mut()
}
pub fn as_effect_context<'side_effect>(
&'side_effect self,
) -> &'side_effect EffectContext<'context, 'battle, 'data> {
&self.context
}
pub fn as_effect_context_mut<'side_effect>(
&'side_effect mut self,
) -> &'side_effect mut EffectContext<'context, 'battle, 'data> {
&mut self.context
}
pub fn source_context<'applying_effect>(
&'applying_effect mut self,
) -> Result<
Option<MonContext<'applying_effect, 'applying_effect, 'applying_effect, 'battle, 'data>>,
> {
match self.source_handle {
None => Ok(None),
Some(source_handle) => self
.as_battle_context_mut()
.mon_context(source_handle)
.map(|mon_context| Some(mon_context)),
}
}
pub fn forward_side_effect_context<'side_effect>(
&'side_effect mut self,
effect_handle: EffectHandle,
) -> Result<SideEffectContext<'side_effect, 'side_effect, 'battle, 'data>> {
let source_effect_handle = self.effect_handle().clone();
let side = unsafe { &*self.side }.index;
let source_handle = self.source_handle;
self.as_battle_context_mut().side_effect_context(
effect_handle,
side,
source_handle,
Some(source_effect_handle),
)
}
pub fn source_side_effect_context<'side_effect>(
&'side_effect mut self,
) -> Result<Option<SideEffectContext<'side_effect, 'side_effect, 'battle, 'data>>> {
match self.source_effect_handle().cloned() {
Some(source_effect_handle) => {
let side = unsafe { &*self.side }.index;
let source_handle = self.source_handle;
Ok(Some(self.as_battle_context_mut().side_effect_context(
source_effect_handle,
side,
source_handle,
None,
)?))
}
None => Ok(None),
}
}
pub fn battle(&self) -> &CoreBattle<'data> {
self.context.battle()
}
pub fn battle_mut(&mut self) -> &mut CoreBattle<'data> {
self.context.battle_mut()
}
pub fn effect_handle(&self) -> &EffectHandle {
self.context.effect_handle()
}
pub fn effect(&self) -> &Effect<'_> {
self.context.effect()
}
pub fn effect_mut(&mut self) -> &mut Effect<'context> {
self.context.effect_mut()
}
pub fn source_effect_handle(&self) -> Option<&EffectHandle> {
self.context.source_effect_handle()
}
pub fn side(&self) -> &Side {
unsafe { &*self.side }
}
pub fn side_mut(&mut self) -> &mut Side {
unsafe { &mut *self.side }
}
pub fn source_handle(&self) -> Option<MonHandle> {
self.source_handle
}
pub fn has_source(&self) -> bool {
self.source.is_some()
}
pub fn source(&self) -> Option<&Mon> {
self.source.as_deref()
}
pub fn source_mut(&mut self) -> Option<&mut Mon> {
self.source.as_deref_mut()
}
}
pub struct FieldEffectContext<'effect, 'context, 'battle, 'data>
where
'data: 'battle,
'battle: 'context,
'context: 'effect,
{
context: MaybeOwnedMut<'effect, EffectContext<'context, 'battle, 'data>>,
source_handle: Option<MonHandle>,
source: Option<&'context mut Mon>,
}
impl<'effect, 'context, 'battle, 'data> FieldEffectContext<'effect, 'context, 'battle, 'data> {
fn new(
context: MaybeOwnedMut<'effect, EffectContext<'context, 'battle, 'data>>,
source_handle: Option<MonHandle>,
) -> Result<Self> {
let source = match source_handle {
None => None,
Some(source_handle) => {
let source = context
.as_battle_context()
.cache
.mon(context.battle(), source_handle)?;
let source = unsafe { source.unsafely_detach_borrow_mut() };
Some(source)
}
};
Ok(Self {
context,
source_handle,
source,
})
}
pub fn as_battle_context<'side_effect>(
&'side_effect self,
) -> &'side_effect Context<'battle, 'data> {
self.context.as_battle_context()
}
pub fn as_battle_context_mut<'side_effect>(
&'side_effect mut self,
) -> &'side_effect mut Context<'battle, 'data> {
self.context.as_battle_context_mut()
}
pub fn as_effect_context<'side_effect>(
&'side_effect self,
) -> &'side_effect EffectContext<'context, 'battle, 'data> {
&self.context
}
pub fn as_effect_context_mut<'side_effect>(
&'side_effect mut self,
) -> &'side_effect mut EffectContext<'context, 'battle, 'data> {
&mut self.context
}
pub fn source_context<'applying_effect>(
&'applying_effect mut self,
) -> Result<
Option<MonContext<'applying_effect, 'applying_effect, 'applying_effect, 'battle, 'data>>,
> {
match self.source_handle {
None => Ok(None),
Some(source_handle) => self
.as_battle_context_mut()
.mon_context(source_handle)
.map(|mon_context| Some(mon_context)),
}
}
pub fn forward_field_effect_context<'side_effect>(
&'side_effect mut self,
effect_handle: EffectHandle,
) -> Result<FieldEffectContext<'side_effect, 'side_effect, 'battle, 'data>> {
let source_effect_handle = self.effect_handle().clone();
let source_handle = self.source_handle;
self.as_battle_context_mut().field_effect_context(
effect_handle,
source_handle,
Some(source_effect_handle),
)
}
pub fn source_field_effect_context<'side_effect>(
&'side_effect mut self,
) -> Result<Option<FieldEffectContext<'side_effect, 'side_effect, 'battle, 'data>>> {
match self.source_effect_handle().cloned() {
Some(source_effect_handle) => {
let source_handle = self.source_handle;
Ok(Some(self.as_battle_context_mut().field_effect_context(
source_effect_handle,
source_handle,
None,
)?))
}
None => Ok(None),
}
}
pub fn battle(&self) -> &CoreBattle<'data> {
self.context.battle()
}
pub fn battle_mut(&mut self) -> &mut CoreBattle<'data> {
self.context.battle_mut()
}
pub fn effect_handle(&self) -> &EffectHandle {
self.context.effect_handle()
}
pub fn effect(&self) -> &Effect<'_> {
self.context.effect()
}
pub fn effect_mut(&mut self) -> &mut Effect<'context> {
self.context.effect_mut()
}
pub fn source_effect_handle(&self) -> Option<&EffectHandle> {
self.context.source_effect_handle()
}
pub fn source_handle(&self) -> Option<MonHandle> {
self.source_handle
}
pub fn has_source(&self) -> bool {
self.source.is_some()
}
pub fn source(&self) -> Option<&Mon> {
self.source.as_deref()
}
pub fn source_mut(&mut self) -> Option<&mut Mon> {
self.source.as_deref_mut()
}
}